#!/usr/bin/env python
# coding: utf-8

# # 支持四则运算乘除先计算，加减后计算

# In[1]:


INTEGER, PLUS, MINUS, MUL, DIV, EOF = 'INTERGER', 'PLUS', 'MINUS', 'MUL', 'DIV', 'EOF'


# In[2]:


class Token:
    """记号类
    """
    def __init__(self, value_type, value):
        self.value_type = value_type # 记号的类型
        self.value = value # 记号的值
    
    def __str__(self):
        """重写查看记号内容的方法"""
        return f"Token({self.value_type}, {self.value})"
    
    def __repr__(self):
        return self.__str__()


# In[3]:


class Lexer:
    """解释器类
    """
    def __init__(self, text):
        self.text = text
        self.position = 0
        self.current_char = self.text[self.position]
    
    def error(self):
        raise Exception('警告：错误的输入内容！')
    
    def advance(self):
        """定义获取下一个字符的方法
        """
        self.position += 1
        if self.position >= len(self.text):
            self.current_char = None
        else:
            self.current_char = self.text[self.position]
    
    def skip_whitespace(self):
        """定义跳过空格的方法
        """
        while self.current_char is not None and self.current_char.isspace():
            self.advance()
    
    def long_integer(self):
        result = ''
        while self.current_char is not None and self.current_char.isdigit():
            result += self.current_char
            self.advance()
        return int(result)
            
    def get_next_token(self):
        while self.current_char is not None:
            if self.current_char.isspace():
                self.skip_whitespace()
                continue
            if self.current_char.isdigit():
                token = Token(INTEGER, self.long_integer())
                return token
            if self.current_char == '+':
                token = Token(PLUS, self.current_char)
                self.advance()
                return token
            if self.current_char == '-':
                token = Token(MINUS, self.current_char)
                self.advance()
                return token
            if self.current_char == '*':
                token = Token(MUL, self.current_char)
                self.advance()
                return token
            if self.current_char == '/':
                token = Token(DIV, self.current_char)
                self.advance()
                return token
            self.error()
        return Token(EOF, None)


# # 支持优先级的文法规则
# 
# * 为每个优先级定义一个非终结符
# * 非终结符所在的产生式的主体应该包含同等级的算数运算符和优先级高一级的非终结符（引用）
# * 创建一个终结符factor作为基本单位，拥有最高优先级
# * 如果有N层优先级，则需要定义N（优先级） + 1（基本单位）个非终结符

# # 支持优先级四则运算的文法
# 
# factor是基本单位，表示整数；
# term表示乘除法；
# expr表示加减法
# 文法从上到下，表达优先级从低到高
# ```
# expr: term((PLUS|MINUS)term)*
# term: factor((MUL|DIV)factor)*
# factor: INTEGER
# ```

# In[4]:


class Interpreter:
    """解释器类
    """
    def __init__(self, lexer):
        self.lexer = lexer
        self.current_token = lexer.get_next_token()
    
    def eat(self, token_type):
        print(self.current_token)
        if self.current_token.value_type == token_type:
            if token_type != EOF:
                self.current_token = self.lexer.get_next_token()
        else:
            self.error()
    
    def factor(self):
        token = self.current_token
        self.eat(INTEGER)
        return token.value
    
    def term(self):
        """乘除法
        """
        result = self.factor()
        
        while self.current_token.value_type in (MUL, DIV):
            if self.current_token.value_type == MUL:
                self.eat(MUL)
                result *= self.factor()
            if self.current_token.value_type == DIV:
                self.eat(DIV)
                result /= self.factor()
        return result

    
    def expr(self):
        """加减法
        """
        result = self.term()
        
        while self.current_token.value_type in (PLUS, MINUS):
            if self.current_token.value_type == PLUS:
                self.eat(PLUS)
                result += self.term()
            if self.current_token.value_type == MINUS:
                self.eat(MINUS)
                result -= self.term()
        return result


# In[5]:


def main():
    while True:
        text = input("输入算式：")
        if text == 'q':
            break
        lexer = Lexer(text)
        interpreter = Interpreter(lexer)
        result = interpreter.expr()
        print(text, "=", result)


# In[6]:


main()

